home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / Source / Telnet 2.6.1d1 4⁄26⁄94 Folder / source / tek / vgtek.c < prev    next >
Text File  |  1993-11-06  |  34KB  |  1,540 lines

  1. /*
  2.  *    vgtek.c by Aaron Contorer 1987 for NCSA
  3.  *    bugfixes by Tim Krauskopf 1988 for NCSA
  4.  *    TEK4105 support by Dave Whittington 1990 (for NCSA, of course)
  5.  *
  6.  *    Takes Tektronix codes as input; sends output to real graphics devices.
  7.  *
  8.  *    CHANGES TO MAKE:
  9.  *    create a function to make sure a window is attached to a real window.
  10.  *      Calling program will call this whenever switching between active windows.
  11.  *    Pass virtual window number to RG driver so it can call back.
  12.  */
  13.  
  14. #ifdef MPW
  15. #pragma segment TEKMAIN
  16. #endif
  17.  
  18. #include <Stdio.h>
  19. #include <Stdlib.h>
  20. #include "TelnetHeader.h"
  21. #include "event.proto.h"
  22. #include "maclook.proto.h"
  23. #include "wind.h"
  24.  
  25. #include "vsdata.h"
  26. #include "vsinterf.proto.h"
  27.  
  28. #include "vgfont.h"
  29. #include "vgtek.proto.h"
  30. #include "rg0.proto.h"
  31. #include "rgmp.proto.h"
  32. #include "tekrgmac.proto.h"
  33. #include "tekdefs.h"    /* NCSA: sb - all defines are now here, for easy access */
  34. #include "tekstor.proto.h"
  35.  
  36.  
  37. extern WindRec *screens;
  38. extern TelInfoRec *TelInfo;
  39.  
  40. static fontnum(short vw, short n);
  41. static storexy(short vw, short x, short y);
  42. static joinup(short hi, short lo, short e);
  43. static newcoord(short vw);
  44. static linefeed(short vw);
  45. static clipvec(short vw, short xa, short ya, short xb, short yb);
  46.  
  47. static struct VGWINTYPE *VGwin[MAXVG];  /* BYU - virtual window descriptors */
  48.  
  49. static char state[MAXVG],savstate[MAXVG];
  50.     /* save state in a parallel array for speed */
  51. static TEKSTOREP VGstore[MAXVG]; /* the store where data for this window is kept */
  52. static char storing[MAXVG]; /* are we currently saving data from this window */
  53. static short drawing[MAXVG]; /* redrawing or not? */
  54.  
  55. static short charxset[NUMSIZES] = {56,51,34,31,112,168};
  56. static short charyset[NUMSIZES] = {88,82,53,48,176,264};
  57.  
  58. /*******************************************************************/
  59.  
  60. void    TEKMAINunload(void) {}
  61.  
  62. short donothing(void)    /* BYU LSC */
  63. {
  64.     return 0;
  65. }
  66.  
  67. /*
  68.  *    Set font for window 'vw' to size 'n'.
  69.  *    Sizes are 0..3 in Tek 4014 standard.
  70.  *    Sizes 4 & 5 are used internally for Tek 4105 emulation.
  71.  */
  72. static fontnum(short vw, short n)
  73. {
  74.     if ((n < 0) || (n >= NUMSIZES)) return(-1);
  75.     VGwin[vw]->fontnum = n;
  76.     VGwin[vw]->charx = charxset[n];
  77.     VGwin[vw]->chary = charyset[n];
  78.     return(0);
  79. }
  80.  
  81.  
  82. static storexy(short vw, short x, short y)
  83. /* set graphics x and y position */
  84. {
  85.     VGwin[vw]->curx = x;
  86.     VGwin[vw]->cury = y;
  87. }
  88.  
  89.  
  90. static joinup(short hi, short lo, short e)
  91. /* returns the number represented by the 3 pieces */
  92. {
  93. #if 1
  94.     return (((hi & 31) << 7) | ((lo & 31) << 2) | (e & 3));
  95. #else
  96.     return (((hi /* & 31 */ ) << 7) | ((lo /* & 31 */ ) << 2) | (e /* & 3 */));
  97. #endif
  98. } /* end joinup() */
  99.  
  100.  
  101. static newcoord(short vw)
  102. /*
  103.  *    Replace x,y with nx,ny
  104.  */
  105. {
  106.     VGwin[vw]->hiy = VGwin[vw]->nhiy;
  107.     VGwin[vw]->hix = VGwin[vw]->nhix;
  108.     VGwin[vw]->loy = VGwin[vw]->nloy;
  109.     VGwin[vw]->lox = VGwin[vw]->nlox;
  110.     VGwin[vw]->ey  = VGwin[vw]->ney;
  111.     VGwin[vw]->ex  = VGwin[vw]->nex;
  112.  
  113.     VGwin[vw]->curx = joinup(VGwin[vw]->nhix,VGwin[vw]->nlox,VGwin[vw]->nex);
  114.     VGwin[vw]->cury = joinup(VGwin[vw]->nhiy,VGwin[vw]->nloy,VGwin[vw]->ney);
  115. }
  116.  
  117.  
  118. static linefeed(short vw) 
  119. /* 
  120.  *    Perform a linefeed & cr (CHARTALL units) in specified window.
  121.  */
  122. {
  123. /*    short y = joinup(VGwin[vw]->hiy,VGwin[vw]->loy,VGwin[vw]->ey);*/
  124.     short y = VGwin[vw]->cury;
  125.     short x;
  126.  
  127.     if (y > VGwin[vw]->chary) y -= VGwin[vw]->chary;
  128.     else
  129.     {
  130.         y = 3119 - VGwin[vw]->chary;
  131.         VGwin[vw]->textcol = 2048 - VGwin[vw]->textcol;
  132.     }
  133.     x = VGwin[vw]->textcol;
  134.     storexy(vw,x,y);
  135. }
  136.  
  137. /*
  138.  *    Draw a vector in vw's window from x0,y0 to x1,y1.
  139.  *    Zoom the vector to the current visible window,
  140.  *    and clip it before drawing it.
  141.  *    Uses Liang-Barsky algorithm from ACM Transactions on Graphics,
  142.  *        Vol. 3, No. 1, January 1984, p. 7.
  143.  *
  144.  *  Note: since QuickDraw on the Mac already handles clipping, we
  145.  *          will not do any processing here.
  146.  *  14may91dsw
  147.  *
  148.  */
  149. static clipvec(short vw, short xa, short ya, short xb, short yb)
  150. {
  151.     short    t,b,l,r;
  152.     struct VGWINTYPE *vp;
  153.     long    hscale, vscale;
  154.     
  155.     vp = VGwin[vw];        /* BYU mod */
  156.  
  157.     hscale = INXMAX / (long) vp->winwide;
  158.     vscale = INYMAX / (long) vp->wintall;
  159.     
  160.     t = vp->wintop;
  161.     b = vp->winbot;
  162.     l = vp->winleft;
  163.     r = vp->winright;
  164.  
  165.     (*RG[vp->RGdevice].drawline) (vp->RGnum,
  166.         (short) ((long)(xa - l) * INXMAX / (long) vp->winwide),
  167.         (short) ((long)(ya- b) * INYMAX / (long) vp->wintall),
  168.         (short) ((long)(xb - l) * INXMAX / (long) vp->winwide),
  169.         (short) ((long)(yb- b) * INYMAX / (long) vp->wintall)
  170.         );
  171. } /* end clipvec() */
  172.  
  173.  
  174. /*
  175.  *    Draw a stroked character at the current cursor location.
  176.  *    Uses simple 8-directional moving, 8-directional drawing.
  177.  *
  178.  *    Modified 17jul90dsw: TEK4105 character set added.
  179.  */
  180. short    drawc(short vw, short c) /* character to draw */
  181. {
  182. short        x,y,savex,savey;
  183. short        strokex,strokey;
  184. short        n;                        /* number of times to perform command */
  185. char    *pstroke;                /* pointer into stroke data */
  186. short        hmag,vmag;
  187. short        xdir,ydir;
  188. short        height;
  189.  
  190.     xdir = 1;
  191.     ydir = 0;
  192.  
  193.     if (c == 10)
  194.     {
  195.         linefeed(vw);
  196.         return(0);
  197.     }
  198.  
  199.     if (c == 7)
  200.     {
  201.         (*RG[VGwin[vw]->RGdevice].bell) (VGwin[vw]->RGnum);
  202.         TEKunstore(VGstore[vw]);
  203.         return(0);
  204.     }
  205.  
  206.     savey = y = VGwin[vw]->cury;
  207.     savex = x = VGwin[vw]->curx;
  208.  
  209.     if (c == 8)
  210.     {
  211.         if (savex <= VGwin[vw]->textcol) return(0);
  212.         savex -= VGwin[vw]->charx;
  213.         if (savex < VGwin[vw]->textcol) savex = VGwin[vw]->textcol;
  214.         VGwin[vw]->cury = savey;
  215.         VGwin[vw]->curx = savex;
  216.         return(0);
  217.     }
  218.  
  219.     if (VGwin[vw]->TEKtype)
  220.     {
  221.         height = VGwin[vw]->TEKSize;
  222.         if (c > 126)
  223.         {
  224.             height = 1;
  225.             (*RG[VGwin[vw]->RGdevice].pencolor)(VGwin[vw]->RGnum,VGwin[vw]->pencolor);
  226.         }
  227.         else
  228.             (*RG[VGwin[vw]->RGdevice].pencolor)(VGwin[vw]->RGnum,VGwin[vw]->TEKIndex);
  229.         hmag = (height*8);
  230.         vmag = (height*8);
  231.         
  232.         xdir = 0;
  233.         switch(VGwin[vw]->TEKRot)
  234.         {
  235.             case 0:
  236.                 xdir = 1;
  237.                 break;
  238.             case 90:
  239.                 ydir = 1;
  240.                 break;
  241.             case 180:
  242.                 xdir = -1;
  243.                 break;
  244.             case 270:
  245.                 ydir = -1;
  246.                 break;
  247.         }
  248.     }
  249.     else
  250.     {
  251.         hmag = VGwin[vw]->charx / 10;
  252.         vmag = VGwin[vw]->chary / 10;
  253.     }
  254.  
  255.     if ((c < 32) || (c > 137))
  256.         return(0);                    // Is this return value correct?
  257.     c -= 32;
  258.     pstroke = (VGwin[vw]->TEKtype) ? VGTEKfont[c] : VGfont[c];
  259.     while (*pstroke)
  260.     {
  261.         strokex = x;
  262.         strokey = y;
  263.         n = (*(pstroke++) - 48);    /* run length */
  264.         c = *(pstroke++);            /* direction code */
  265.  
  266.         switch(c)     /* horizontal movement: positive = right */
  267.         {
  268.         case 'e': case 'd': case 'c': case 'y': case 'h': case 'n':
  269.             x += (n * hmag) * xdir;
  270.             y += (n * hmag) * ydir;
  271.             break;
  272.         case 'q': case 'a': case 'z': case 'r': case 'f': case 'v':
  273.             x -= (n * hmag) * xdir;
  274.             y -= (n * hmag) * ydir;
  275.         }
  276.  
  277.         switch(c)    /* vertical movement: positive = up */
  278.         {
  279.         case 'q': case 'w': case 'e': case 'r': case 't': case 'y':
  280.             x -= (n * vmag) * ydir;
  281.             y += (n * vmag) * xdir;
  282.             break;
  283.         case 'z': case 'x': case 'c': case 'v': case 'b': case 'n':
  284.             x += (n * vmag) * ydir;
  285.             y -= (n * vmag) * xdir;
  286.         }
  287.  
  288.         switch(c)    /* draw or move */
  289.         {
  290.         case 'r': case 't': case 'y': case 'f': case 'h':
  291.         case 'v': case 'b': case 'n':
  292.             clipvec (vw,strokex,strokey,x,y);
  293.             break;
  294.         }
  295.     
  296.     } /* end while not at end of string */
  297.  
  298.     /* Update cursor location to next char position */
  299.     savex += VGwin[vw]->charx * xdir;
  300.     savey += VGwin[vw]->charx * ydir;
  301.     if ((savex < 0) || (savex > 4095) || (savey < 0) || (savey > 3119))
  302.     {
  303.         savex = savex < 0 ? 0 : savex > 4095 ? 4095 : savex;
  304.         savey = savey < 0 ? 0 : savey > 3119 ? 3119 : savey;
  305.     }
  306.  
  307.     if (VGwin[vw]->TEKtype)
  308.         (*RG[VGwin[vw]->RGdevice].pencolor)(VGwin[vw]->RGnum,VGwin[vw]->pencolor);
  309.  
  310.     VGwin[vw]->cury = savey;
  311.     VGwin[vw]->curx = savex;
  312. }
  313.  
  314. /***********************************************************
  315. ************************************************************
  316. ***                                                         ***
  317. **    All routines given below may be called by the user      **
  318. **    program.  No routines given above may be called from  **
  319. **    the user program.                                      **
  320. ***                                                         ***
  321. ************************************************************
  322. ***********************************************************/
  323.  
  324. void VGalloc(void)        /* BYU - allocate this structure to save global space */
  325. {                /* BYU */
  326.     short i;        /* BYU */
  327.                                     /* BYU */
  328.     for (i=0; i<MAXVG; i++) {        /* BYU */
  329.         VGwin[i] = (struct VGWINTYPE *) NewPtrClear(sizeof(struct VGWINTYPE));
  330.         VGwin[i]->id = 'VGWN';
  331.     }            /* BYU */
  332. }                /* BYU */
  333.  
  334.  
  335. /*
  336.  *    Initialize the whole VG environment.  Should be called ONCE
  337.  *    at program startup before using the VG routines.
  338.  */
  339. void VGinit
  340.   (
  341.     void
  342.   )
  343. {
  344. short i;
  345.  
  346.     for (i = 0; i < MAXVG; i++)
  347.     {
  348.         VGwin[i]->RGdevice = -1; /* no device */
  349.     }                                                /* BYU LSC */
  350. #ifndef DEBUG
  351.     for (i=0; i<MAXRG; i++) (*RG[i].init)();        /* BYU LSC */
  352. #endif
  353. }
  354.  
  355. /*
  356.  *    Detach window from its current device and attach it to the
  357.  *    specified device.  Returns negative number if unable to do so.
  358.  *    Sample application:  switching an image from #9 to Hercules.
  359.  *    Must redraw after calling this.
  360.  */
  361. short    VGdevice(short vw, short dev)
  362. {
  363. short newwin;
  364.  
  365.     newwin = (*RG[dev].newwin)();
  366.     if (newwin<0) return(newwin);    /* unable to open new window */
  367.  
  368.     (*RG[VGwin[vw]->RGdevice].close)(VGwin[vw]->RGnum);
  369.     VGwin[vw]->RGdevice = dev;
  370.     VGwin[vw]->RGnum = newwin;
  371.     VGwin[vw]->pencolor = 1;
  372.     VGwin[vw]->TEKBackground = 0;
  373.     fontnum(vw,1);
  374.     return(0);
  375. }
  376.  
  377.  
  378. /*
  379.  *    create a new VG window and return its number.
  380.  *    New window will be attached to specified real device.
  381.  *    Returns -1 if unable to create a new VG window.
  382.  *
  383.  *    Modified 16jul90dsw: Support selection of 4105 or 4014.
  384.  */
  385. short VGnewwin
  386.   (
  387.     short device, /* number of RG device to use */
  388.     short theVS
  389.   )
  390. {
  391. short vw = 0;
  392. short    theScrn;
  393.  
  394.     while ((vw < MAXVG) && (VGwin[vw]->RGdevice != -1)) vw++;
  395.     if (vw == MAXVG)
  396.         return(-1);
  397.     VGstore[vw] = newTEKstore();
  398.  
  399.     if (VGstore[vw] == NULL)
  400.         return(-1);                    /* Burp.  No memory. */
  401.     VGwin[vw]->RGdevice = device;
  402.     VGwin[vw]->RGnum = (*RG[device].newwin)();
  403.  
  404.     theScrn = findbyVS(theVS);
  405.     VGwin[vw]->TEKtype = screens[theScrn].tektype;    // 0 = 4014, 1 = 4105
  406.  
  407.     if (VGwin[vw]->RGnum < 0)
  408.     {
  409.         /* no windows available on device */
  410.         freeTEKstore(VGstore[vw]);
  411.         VGwin[vw]->RGdevice = -1;    /* Added 16jul90dsw: seems like this is needed. */
  412.         return(-1);
  413.     }
  414.             
  415.     VGwin[vw]->mode = ALPHA;
  416.     VGwin[vw]->TEKPanel = (pointlist) NULL;
  417.     VGwin[vw]->theVS = theVS;
  418.     state[vw] = DONE;
  419.     storing[vw] = TRUE;
  420.     VGwin[vw]->textcol = 0;
  421.     drawing[vw] = 1;
  422.     fontnum(vw,0);
  423.     (*RG[device].pencolor)(VGwin[vw]->RGnum,1);
  424.  
  425.     storexy(vw,0,3071);
  426. #if 1                                        /* BYU LSC */
  427.     VGzoom(vw,0,0,4095,3119);                /* BYU LSC - important */
  428. #else                                        /* BYU LSC */
  429.     VGzoom(vw,0,0,INXMAX-1,INYMAX-1);
  430. #endif                                        /* BYU LSC */
  431.     return(vw);
  432. }
  433.  
  434.  
  435. /* 
  436.  *    Clear the store associated with window vw.  
  437.  *    All contents are lost.
  438.  *    User program can call this whenever desired.
  439.  *    Automatically called after receipt of Tek page command.
  440.  */
  441. void    VGclrstor(short vw)
  442. {
  443.     freeTEKstore(VGstore[vw]);
  444.     VGstore[vw] = newTEKstore();
  445.         /* Don't have to check for errors --    */
  446.         /* there was definitely enough memory.    */
  447. }
  448.  
  449.  
  450. void    VGdumpstore(short vw, short (*func )(short))
  451. /*
  452.  *    Successively call the function pointed to by 'func' for each
  453.  *    character stored from window vw.  Each character will
  454.  *    be passed in integer form as the only parameter.  A value of -1
  455.  *    will be passed on the last call to indicate the end of the data.
  456.  */
  457. {
  458.     short        data;
  459.     TEKSTOREP    st = VGstore[vw];
  460.  
  461.     topTEKstore(st);
  462.     while ((data = nextTEKitem(st)) != -1) (*func)(data);
  463.     (*func)(-1);
  464. }
  465.  
  466.  
  467. /*
  468.  *    This is the main Tek emulator process.  Pass it the window and
  469.  *    the latest input character, and it will take care of the rest.
  470.  *    Calls RG functions as well as local zoom and character drawing
  471.  *    functions.
  472.  *
  473.  *    Modified 16jul90dsw:
  474.  *        Added 4105 support.
  475.  */
  476. void VGdraw(short vw, char c)            /* the latest input char */
  477. {
  478. char    cmd;
  479. char    value;
  480. char    goagain;    /* true means go thru the function a second time */
  481. char    temp[80];
  482. RgnHandle    PanelRgn;
  483. struct    VGWINTYPE *vp;
  484. pointlist temppoint;
  485.  
  486.     vp = VGwin[vw];        /* BYU */
  487.  
  488.     temp[0] = c;
  489.     temp[1] = (char) 0;
  490.  
  491.     /*** MAIN LOOP ***/
  492.      do
  493.     {
  494.         c &= 0x7f;                /* BYU 2.4.15 */
  495.          cmd = (c >> 5) & 0x03;
  496.         value = c & 0x1f;
  497.         goagain = FALSE;
  498.  
  499.         switch(state[vw])
  500.         {
  501.         case HIY: /* beginning of a vector */
  502.             vp->nhiy = vp->hiy;
  503.             vp->nhix = vp->hix;
  504.             vp->nloy = vp->loy;
  505.             vp->nlox = vp->lox;
  506.             vp->ney  = vp->ey;
  507.             vp->nex  = vp->ex;
  508.             
  509.             switch(cmd)
  510.             {
  511.             case 0:
  512.                 if (value == 27)        /* escape sequence */
  513.                 {
  514.                     state[vw] = ESCOUT;
  515.                     savstate[vw] = HIY;
  516.                 }
  517.                 else if (value < 27)    /* ignore */
  518.                 {
  519.                     break;
  520.                 }
  521.                 else
  522.                 {
  523.                     state[vw] = CANCEL;
  524.                     goagain = TRUE;
  525.                 }
  526.                 break;
  527.             case 1:                        /* hiy */
  528.                 vp->nhiy = value;
  529.                 state[vw] = EXTRA;
  530.                 break;
  531.             case 2:                        /* lox */
  532.                 vp->nlox = value;
  533.                 state[vw] = DONE;
  534.                 break;
  535.             case 3:                        /* extra or loy */
  536.                 vp->nloy = value;
  537.                 state[vw] = LOY;
  538.                 break;
  539.             }
  540.             break;        
  541.         case ESCOUT:
  542.             if ((value != 13) && (value != 10) && (value != 27) && (value != '~'))
  543.             {
  544.                 state[vw] = savstate[vw];        /* skip all EOL-type characters */
  545.                 goagain = TRUE;
  546.             }
  547.             break;
  548.         case EXTRA:    /* got hiy; expecting extra or loy */
  549.             switch(cmd)
  550.             {
  551.             case 0:
  552.                 if (value == 27)        /* escape sequence */
  553.                 {
  554.                     state[vw] = ESCOUT;
  555.                     savstate[vw] = EXTRA;
  556.                 }
  557.                 else if (value < 27)    /* ignore */
  558.                 {
  559.                     break;
  560.                 }
  561.                 else
  562.                 {
  563.                     state[vw] = DONE;
  564.                     goagain = TRUE;
  565.                 }
  566.                 break;
  567.             case 1:                        /* hix */
  568.                 vp->nhix = value;
  569.                 state[vw] = LOX;
  570.                 break;
  571.             case 2:                        /* lox */
  572.                 vp->nlox = value;
  573.                 state[vw] = DONE;
  574.                 break;
  575.             case 3:                        /* extra or loy */
  576.                 vp->nloy = value;
  577.                 state[vw] = LOY;
  578.                 break;
  579.             }
  580.             break;
  581.         case LOY: /* got extra or loy; next may be loy or something else */
  582.             switch(cmd)
  583.             {
  584.             case 0:
  585.                 if (value == 27)        /* escape sequence */
  586.                 {
  587.                     state[vw] = ESCOUT;
  588.                     savstate[vw] = LOY;
  589.                 }
  590.                 else if (value < 27)    /* ignore */
  591.                 {
  592.                     break;
  593.                 }
  594.                 else
  595.                 {
  596.                     state[vw] = DONE;
  597.                     goagain = TRUE;
  598.                 }
  599.                 break;
  600.             case 1: /* hix */
  601.                 vp->nhix = value;
  602.                 state[vw] = LOX;
  603.                 break;
  604.             case 2: /* lox */
  605.                 vp->nlox = value;
  606.                 state[vw] = DONE;
  607.                 break;
  608.             case 3: /* this is loy; previous loy was really extra */
  609.                 vp->ney = (vp->nloy >> 2) & 3;
  610.                 vp->nex = vp->nloy & 3;
  611.                 vp->nloy = value;
  612.                 state[vw] = HIX;
  613.                 break;
  614.             }
  615.             break;
  616.         case HIX:                        /* hix or lox */
  617.             switch(cmd)
  618.             {
  619.             case 0:
  620.                 if (value == 27)        /* escape sequence */
  621.                 {
  622.                     state[vw] = ESCOUT;
  623.                     savstate[vw] = HIX;
  624.                 }
  625.                 else if (value < 27)    /* ignore */
  626.                 {
  627.                     break;
  628.                 }
  629.                 else
  630.                 {
  631.                     state[vw] = DONE;
  632.                     goagain = TRUE;
  633.                 }
  634.                 break;
  635.             case 1:                        /* hix */
  636.                 vp->nhix = value;
  637.                 state[vw] = LOX;
  638.                 break;
  639.             case 2:                        /* lox */
  640.                 vp->nlox = value;
  641.                 state[vw] = DONE;
  642.                 break;
  643.             }
  644.              break;
  645.     
  646.         case LOX:                        /* must be lox */
  647.             switch(cmd)
  648.             {
  649.             case 0:
  650.                 if (value == 27)        /* escape sequence */
  651.                 {
  652.                     state[vw] = ESCOUT;
  653.                     savstate[vw] = LOX;
  654.                 }
  655.                 else if (value < 27)    /* ignore */
  656.                 {
  657.                     break;
  658.                 }
  659.                 else
  660.                 {
  661.                     state[vw] = DONE;
  662.                     goagain = TRUE;
  663.                 }
  664.                 break;
  665.             case 2:
  666.                 vp->nlox = value;
  667.                 state[vw] = DONE;
  668.                 break;
  669.             }
  670.             break;
  671.     
  672.         case ENTERVEC:
  673.             if (c == 7) vp->mode = DRAW;
  674.             if (c < 32)
  675.             {
  676.                 state[vw] = DONE;
  677.                 goagain = TRUE;
  678.                 vp->mode = DONE;
  679.                 break;
  680.             }
  681.             state[vw] = HIY;
  682.             vp->mode = TEMPMOVE;
  683.             vp->modesave = DRAW;
  684.             goagain = TRUE;
  685.             break;
  686.         case RS:
  687.             switch (c)
  688.             {
  689.             case ' ':                /* pen up */
  690.                 vp->modesave = vp->mode;
  691.                 vp->mode = TEMPMOVE;
  692.                 break;
  693.             case 'P':                /* pen down */
  694.                 vp->mode = DRAW;
  695.                 break;
  696.             case 'D':                /* move up */
  697.                 vp->cury++;
  698.                 break;
  699.             case 'E':
  700.                 vp->cury++;
  701.                 vp->curx++;
  702.                 break;
  703.             case 'A':
  704.                 vp->curx++;
  705.                 break;
  706.             case 'I':
  707.                 vp->curx++;
  708.                 vp->cury--;
  709.                 break;
  710.             case 'H':
  711.                 vp->cury--;
  712.                 break;
  713.             case 'J':
  714.                 vp->curx--;
  715.                 vp->cury--;
  716.                 break;
  717.             case 'B':
  718.                 vp->curx--;
  719.                 break;
  720.             case 'F':
  721.                 vp->cury++;
  722.                 vp->curx--;
  723.                 break;
  724.             case 27:
  725.                 savstate[vw] = RS;
  726.                 state[vw] = ESCOUT;
  727.                 break;
  728.             default:
  729. /*                storexy(vw,vp->curx,vp->cury);*/
  730.                 state[vw] = CANCEL;
  731.                 goagain = TRUE;
  732.                 break;
  733.             }
  734.             if (vp->mode == DRAW)
  735.                 clipvec(vw,vp->curx,vp->cury,vp->curx,vp->cury);
  736.             break;
  737.         case CMD0: /* *->CMD0: get 1st letter of cmd */
  738.             switch(c)
  739.             {
  740.             case 29:                    /* GS, start draw */
  741.                 state[vw] = DONE;
  742.                 goagain = TRUE;
  743.                 break;
  744.             case '%':
  745.                 state[vw] = TERMSTAT;
  746.                 break;
  747.             case '8':
  748.                 fontnum(vw,0);
  749.                 state[vw] = DONE;
  750.                 break;
  751.             case '9':
  752.                 fontnum(vw,1);
  753.                 state[vw] = DONE;
  754.                 break;
  755.             case ':':
  756.                 fontnum(vw,2);
  757.                 state[vw] = DONE;
  758.                 break;
  759.             case ';':
  760.                 fontnum(vw,3);
  761.                 state[vw] = DONE;
  762.                 break;
  763.             case 12: /* form feed = clrscr */
  764.                 if (screens[findbyVS(vp->theVS)].tekclear) {
  765.                     VGpage(vw);
  766.                     VGclrstor(vw);
  767.                 }
  768.                 break;
  769.             case 'L':
  770.                 state[vw] = SOMEL;
  771.                 break;
  772.             case 'K':
  773.                 state[vw] = IGNORE;
  774.                 break;
  775.             case 'M':
  776.                 state[vw] = SOMEM;
  777.                 break;
  778.             case 'R':
  779.                 state[vw] = SOMER;
  780.                 break;
  781.             case 'T':
  782.                 state[vw] = SOMET;
  783.                 break;
  784.             case 26:
  785.                 (*RG[vp->RGdevice].gin)(vp->RGnum);
  786.                 TEKunstore(VGstore[vw]);
  787.                 TEKunstore(VGstore[vw]);
  788.                 break;
  789.             case 10:
  790.             case 13:
  791.             case 27:
  792.             case '~':
  793.                 savstate[vw] = DONE;
  794.                 state[vw] = ESCOUT;
  795.                 break;            /* completely ignore these after ESC */
  796.             default:
  797.                 state[vw] = DONE;
  798.             }
  799.             break;
  800.         case TERMSTAT:
  801.             switch(c)
  802.             {
  803.                 case '!':
  804.                     state[vw] = INTEGER;        /* Drop the next integer */
  805.                     savstate[vw] = DONE;
  806.                     break;
  807.             }
  808.             break;
  809.         case SOMER:
  810.             switch(c)
  811.             {
  812.                 case 'A':
  813.                     state[vw] = INTEGER;
  814.                     savstate[vw] = VIEWAT;
  815.                     break;
  816.             }
  817.             break;
  818.         case VIEWAT:
  819.             state[vw] = INTEGER;
  820.             savstate[vw] = VIEWAT2;
  821.             goagain = TRUE;
  822.             break;
  823.         case VIEWAT2:
  824.             vp->TEKBackground = vp->intin < 0 ? 0 : vp->intin > 7 ? 7 : vp->intin;
  825.             state[vw] = INTEGER;
  826.             savstate[vw] = DONE;
  827.             goagain = TRUE;
  828.             break;
  829.         case SOMET:                /* Got ESC T; now handle 3rd char. */
  830.             switch(c)
  831.             {
  832.             case 'C':            /* GCURSOR */
  833.                 vp->intin = 3;
  834.                 state[vw] = STARTDISC;
  835.                 break;
  836.             case 'D':
  837.                 vp->intin = 2;
  838.                 state[vw] = STARTDISC;
  839.                 break;
  840.             case 'F':            /* set dialog area color map */
  841.                 state[vw] = JUNKARRAY;
  842.                 break;
  843.             case 'G':            /* set surface color map */
  844.                 state[vw] = INTEGER;
  845.                 savstate[vw] = JUNKARRAY;
  846.                 break;
  847.             default:
  848.                 state[vw] = DONE;
  849.             }            
  850.             break;
  851.         case JUNKARRAY:            /* This character is the beginning of an integer
  852.                                     array to be discarded.  Get array size. */
  853.             savstate[vw] = STARTDISC;
  854.             state[vw] = INTEGER;
  855.             break;                    
  856.         case STARTDISC:            /* Begin discarding integers. */
  857.             vp->count = vp->intin + 1;
  858.             goagain = TRUE;
  859.             state[vw] = DISCARDING;
  860.             break;
  861.         case DISCARDING:
  862.             /* We are in the process of discarding an integer array. */
  863.             goagain = TRUE;
  864.             if (!(--(vp->count))) state[vw] = DONE;
  865.             else if (vp->count == 1)
  866.             {
  867.                 state[vw] = INTEGER;
  868.                 savstate[vw] = DONE;
  869.             }
  870.             else
  871.             {
  872.                 state[vw] = INTEGER;
  873.                 savstate[vw] = DISCARDING;
  874.             }
  875.             break;
  876.         case INTEGER:
  877.             if (c & 0x40)
  878.             {
  879.                 vp->intin = c & 0x3f;
  880.                 state[vw] = INTEGER1;
  881.             }
  882.             else
  883.             {
  884.                 vp->intin = c & 0x0f;
  885.                 if (!(c & 0x10)) vp->intin *= -1;
  886.                 state[vw] = savstate[vw];
  887.             }
  888.             break;
  889.         case INTEGER1:
  890.             if (c & 0x40)
  891.             {
  892.                 vp->intin = (vp->intin << 6) | (c & 0x3f);
  893.                 state[vw] = INTEGER2;
  894.             }
  895.             else
  896.             {
  897.                 vp->intin = (vp->intin << 4) | (c & 0x0f);
  898.                 if (!(c & 0x10)) vp->intin *= -1;
  899.                 state[vw] = savstate[vw];
  900.             }
  901.             break;
  902.         case INTEGER2:
  903.             vp->intin = (vp->intin << 4) | (c & 0x0f);
  904.             if (!(c & 0x10)) vp->intin *= -1;
  905.             state[vw] = savstate[vw];
  906.             break;
  907.         case IGNORE:            /* ignore next char; it's not supported */
  908.             state[vw] = DONE;
  909.             break;
  910.         case IGNORE2:            /* ignore next 2 chars */
  911.             state[vw] = IGNORE;
  912.             break;
  913.         case SOMEL:                /* now process 2nd letter */
  914.             switch(c)
  915.             {
  916.             case 'E':                    /* END PANEL 25jul90dsw */
  917.                 if (vp->TEKtype)
  918.                 {
  919.                     if (vp->TEKPanel)
  920.                     {
  921.                         if ((vp->current->x != vp->savx) ||
  922.                             (vp->current->y != vp->savy))
  923.                         {
  924.                             temppoint = (pointlist) NewPtr(sizeof(point));
  925.                             temppoint->x = vp->savx;
  926.                             temppoint->y = vp->savy;
  927.                             temppoint->next = (pointlist) NULL;
  928.                             vp->current->next = temppoint;
  929.                         }
  930.                         temppoint = vp->current = vp->TEKPanel;
  931.                         vp->savx = vp->curx = vp->current->x;
  932.                         vp->savy = vp->cury = vp->current->y;
  933.                         vp->current = vp->current->next;
  934.                         DisposPtr((Ptr) temppoint);
  935.                         PanelRgn = NewRgn();
  936.                         OpenRgn();
  937.                         while (vp->current)
  938.                         {
  939.                             clipvec(vw,vp->curx,vp->cury,
  940.                                     vp->current->x,vp->current->y);
  941.                             temppoint = vp->current;
  942.                             vp->curx = vp->current->x;
  943.                             vp->cury = vp->current->y;
  944.                             vp->current = vp->current->next;
  945.                             DisposPtr((Ptr) temppoint);
  946.                         }
  947.                         CloseRgn(PanelRgn);
  948.                         if (vp->TEKPattern <= 0)
  949.                             (*RG[vp->RGdevice].pencolor)(vp->RGnum,-vp->TEKPattern);
  950.                         PaintRgn(PanelRgn);
  951.                 /*        if (vp->TEKOutline) 
  952.                             FrameRgn(PanelRgn); */
  953.                         DisposeRgn(PanelRgn);
  954.                         (*RG[vp->RGdevice].pencolor)(vp->RGnum,vp->pencolor);
  955.                         vp->TEKPanel = (pointlist) NULL;
  956.                         vp->curx = vp->savx;
  957.                         vp->cury = vp->savy;
  958.                     }
  959.                 }
  960.                 state[vw] = DONE;
  961.                 break;
  962.             case 'F':                    /* MOVE */
  963.                 vp->modesave = vp->mode;
  964.                 vp->mode = TEMPMOVE;
  965.                 state[vw] = HIY;
  966.                 break;
  967.             case 'G':                    /* DRAW */
  968.                 vp->modesave = vp->mode;
  969.                 vp->mode = TEMPDRAW;
  970.                 state[vw] = HIY;
  971.                 break;
  972.             case 'H':                    /* MARKER */
  973.                 vp->modesave = vp->mode;
  974.                 vp->mode = TEMPMARK;
  975.                 state[vw] = HIY;
  976.                 break;
  977.             case 'I':                    /* DAINDEX 24jul90dsw*/
  978.                 state[vw] = STARTDISC;
  979.                 vp->intin = 3;
  980.                 break;
  981.             case 'L':
  982.                 state[vw] = INTEGER;
  983.                 savstate[vw] = DONE;
  984.                 break;
  985.             case 'P':                    /* BEGIN PANEL 17jul90dsw */
  986.                 if (vp->TEKtype)        /* 4105 only */
  987.                 {
  988.                     state[vw] = HIY;
  989.                     vp->mode = PANEL;
  990.                 }
  991.                 else
  992.                     state[vw] = DONE;
  993.                 break;
  994.             case 'T':                    /* GTEXT 17jul90dsw */
  995.                 if (vp->TEKtype)        /* 4105 only */
  996.                 {
  997.                     savstate[vw] = GTEXT;
  998.                     state[vw] = INTEGER;
  999.                 }
  1000.                 else
  1001.                     state[vw] = DONE;
  1002.                 break;
  1003.             default:
  1004.                 state[vw] = DONE;
  1005.             }
  1006.             break;
  1007.         case SOMEM:
  1008.             switch(c)
  1009.             {
  1010.             case 'C':                    /* set graphtext size */
  1011.                 savstate[vw] = GTSIZE0;
  1012.                 state[vw] = INTEGER;
  1013.                 break;
  1014.             case 'L':                    /* set line index */
  1015.                 savstate[vw] = COLORINT;
  1016.                 state[vw] = INTEGER;
  1017.                 break;
  1018.             case 'M':                    /* MARKERTYPE 17jul90dsw */
  1019.                 if (vp->TEKtype)
  1020.                 {
  1021.                     savstate[vw] = MARKER;
  1022.                     state[vw] = INTEGER;
  1023.                 }
  1024.                 else
  1025.                     state[vw] = DONE;
  1026.                 break;
  1027.             case 'N':                    /* GTPATH 17jul90dsw */
  1028.                 if (vp->TEKtype)
  1029.                 {
  1030.                     savstate[vw] = GTPATH;
  1031.                     state[vw] = INTEGER;
  1032.                 }
  1033.                 else
  1034.                     state[vw] = DONE;
  1035.                 break;
  1036.             case 'P':                    /* FillPattern 17jul90dsw */
  1037.                 if (vp->TEKtype)
  1038.                 {
  1039.                     savstate[vw] = FPATTERN;
  1040.                     state[vw] = INTEGER;
  1041.                 }
  1042.                 else
  1043.                     state[vw] = DONE;
  1044.                 break;
  1045.             case 'R':                    /* GTROT 17jul90dsw */
  1046.                 if (vp->TEKtype)
  1047.                 {
  1048.                     savstate[vw] = GTROT;
  1049.                     state[vw] = INTEGER;
  1050.                 }
  1051.                 else
  1052.                     state[vw] = DONE;
  1053.                 break;
  1054.             case 'T':                    /* GTINDEX 17jul90dsw */
  1055.                 if (vp->TEKtype)
  1056.                 {
  1057.                     savstate[vw] = GTINDEX;
  1058.                     state[vw] = INTEGER;
  1059.                 }
  1060.                 else
  1061.                     state[vw] = DONE;
  1062.                 break;
  1063.             case 'V':
  1064.                 if (vp->TEKtype)
  1065.                 {
  1066.                     state[vw] = INTEGER;
  1067.                     savstate[vw] = DONE;
  1068.                 }
  1069.                 else
  1070.                     state[vw] = DONE;
  1071.                 break;
  1072.             default:
  1073.                 state[vw] = DONE;
  1074.             }
  1075.             break;
  1076.         case COLORINT:                /* set line index; have integer */
  1077.             vp->pencolor = vp->intin;
  1078.             (*RG[vp->RGdevice].pencolor)(vp->RGnum,vp->intin);
  1079.             state[vw] = CANCEL;
  1080.             goagain = TRUE;            /* we ignored current char; now process it */
  1081.             break;
  1082.         case GTSIZE0:                /* discard the first integer; get the 2nd */
  1083.             state[vw] = INTEGER;    /* get the important middle integer */
  1084.             savstate[vw] = GTSIZE1;
  1085.             goagain = TRUE;
  1086.             break;
  1087.         case GTSIZE1:                /* integer is the height */
  1088.             if (vp->TEKtype)
  1089.             {
  1090.                 if (vp->intin < 88) vp->TEKSize = 1;
  1091.                 else if ((vp->intin > 87) && (vp->intin < 149)) vp->TEKSize = 2;
  1092.                 else if ((vp->intin > 148) && (vp->intin < 209)) vp->TEKSize = 3;
  1093.                 else if (vp->intin > 208) vp->TEKSize = vp->intin / 61;
  1094.                 VGwin[vw]->charx = (vp->TEKSize * 52);
  1095.                 VGwin[vw]->chary = (vp->TEKSize * 64);
  1096.             }
  1097.             else
  1098.             {
  1099.                 if (vp->intin < 88)
  1100.                     fontnum(vw,0);
  1101.                 else if (vp->intin < 149)
  1102.                     fontnum(vw,4);
  1103.                 else
  1104.                     fontnum(vw,5);
  1105.             }
  1106.             state[vw] = INTEGER;    /* discard last integer */
  1107.             savstate[vw] = DONE;
  1108.             goagain = TRUE;
  1109.             break;
  1110.         case GTEXT:                    /* TEK4105 GraphText output.  17jul90dsw */
  1111.             if (vp->intin > 0)
  1112.             {
  1113.                 drawc(vw,(short) c);    /* Draw the character */
  1114.                 vp->intin--;        /* One less character in the string... */
  1115.             }
  1116.             else
  1117.             {
  1118.                 goagain = TRUE;
  1119.                 state[vw] = DONE;
  1120.                 newcoord(vw);
  1121.             }
  1122.             break;
  1123.         case MARKER:                /* TEK4105 Set marker type.  17jul90dsw */
  1124.             vp->TEKMarker = vp->intin;
  1125.             if (vp->TEKMarker > 10) vp->TEKMarker = 10;
  1126.             if (vp->TEKMarker <  0) vp->TEKMarker = 0;
  1127.             state[vw] = DONE;
  1128.             goagain = TRUE;
  1129.             break;
  1130.         case GTPATH:
  1131.             vp->TEKPath = vp->intin;
  1132.             state[vw] = DONE;
  1133.             goagain = TRUE;
  1134.             break;
  1135.         case FPATTERN:
  1136.             vp->TEKPattern = (vp->intin <  -7) ?  -7 :
  1137.                              (vp->intin > 149) ? 149 : vp->intin;
  1138.             state[vw] = DONE;
  1139.             goagain = TRUE;
  1140.             break;
  1141.         case GTROT:
  1142.             vp->TEKRot = vp->intin;
  1143.             state[vw] = INTEGER;
  1144.             savstate[vw] = GTROT1;
  1145.             goagain = TRUE;
  1146.             break;
  1147.         case GTROT1:
  1148.             vp->TEKRot = (vp->TEKRot) << (vp->intin);
  1149.             vp->TEKRot = ((vp->TEKRot + 45) / 90) * 90;
  1150.             state[vw] = DONE;
  1151.             goagain = TRUE;
  1152.             break;
  1153.         case GTINDEX:
  1154.             vp->TEKIndex = (vp->intin < 0) ? 0 : (vp->intin > 7) ? 7 : vp->intin;
  1155.             state[vw] = DONE;
  1156.             goagain = TRUE;
  1157.             break;
  1158.         case PANEL:
  1159.             vp->TEKOutline = (vp->intin == 0) ? 0 : 1;
  1160.             temppoint = (pointlist) NewPtr(sizeof(point));
  1161.             if (vp->TEKPanel)
  1162.             {
  1163.                 if ((vp->current->x != vp->savx) && (vp->current->y != vp->savy))
  1164.                 {
  1165.                     temppoint->x = vp->savx;
  1166.                     temppoint->y = vp->savy;
  1167.                     vp->current->next = temppoint;
  1168.                     vp->current = temppoint;
  1169.                     temppoint = (pointlist) NewPtr(sizeof(point));
  1170.                 }
  1171.                 vp->current->next = temppoint;
  1172.             }
  1173.             else vp->TEKPanel = temppoint;
  1174.             vp->current = temppoint;
  1175.             vp->current->x = vp->savx = joinup(vp->nhix,vp->nlox,vp->nex);
  1176.             vp->current->y = vp->savy = joinup(vp->nhiy,vp->nloy,vp->ney);
  1177.             vp->current->next = (pointlist) NULL;
  1178.             state[vw] = INTEGER;
  1179.             savstate[vw] = PANEL;
  1180.             vp->mode = DONE;
  1181.             newcoord(vw);
  1182.             state[vw] = DONE;
  1183.             goagain = TRUE;
  1184.             break;
  1185.         case DONE:                    /* ready for anything */
  1186.             switch(c)
  1187.             {
  1188.             case 31:                /* US - enter ALPHA mode */
  1189.                 vp->mode = ALPHA; 
  1190.                 state[vw] = CANCEL;
  1191.                 break;
  1192.             case 30:
  1193.                 state[vw] = RS;
  1194.                 break;
  1195.             case 28:
  1196.                 if (vp->TEKtype)
  1197.                 {
  1198.                     vp->mode = MARK;
  1199.                     state[vw] = HIY;
  1200.                 }
  1201.                 break;
  1202.             case 29:                /* GS - enter VECTOR mode */
  1203.                 state[vw] = ENTERVEC;
  1204.                 break;
  1205.             case 27:
  1206.                 state[vw] = CMD0;
  1207.                 break;
  1208.             default:
  1209.                 if (vp->mode == ALPHA)
  1210.                 {
  1211.                     state[vw] = DONE;
  1212.                     if (! vp->TEKtype)
  1213.                         drawc(vw,(short) c);
  1214.                     else
  1215.                     {
  1216.                         VSwrite(vp->theVS,&c,1);
  1217.                         TEKunstore(VGstore[vw]);
  1218.                     }
  1219.                     return;
  1220.                 }
  1221.                 else if ((vp->mode == DRAW) && cmd)
  1222.                 {
  1223.                     state[vw] = HIY;
  1224.                     goagain = TRUE;
  1225.                 }
  1226.                 else if ((vp->mode == MARK) && cmd)
  1227.                 {
  1228.                     state[vw] = HIY;
  1229.                     goagain = TRUE;
  1230.                 }
  1231.                 else if ((vp->mode == DRAW) && ((c == 13) || (c == 10)))
  1232.                 {
  1233.                     /* break drawing mode on CRLF */
  1234.                     vp->mode = ALPHA; 
  1235.                     state[vw] = CANCEL;
  1236.                 }
  1237.                 else
  1238.                 {
  1239.                     state[vw] = DONE;            /* do nothing */
  1240.                     return;
  1241.                 }
  1242.             }
  1243.         }
  1244.     
  1245.         if (state[vw] == DONE)
  1246.         {
  1247.             if (vp->mode == PANEL)
  1248.             {
  1249.                 vp->mode = DONE;
  1250.                 state[vw] = INTEGER;
  1251.                 savstate[vw] = PANEL;
  1252.             }
  1253.             else if ((vp->TEKPanel) && ((vp->mode == DRAW) || (vp->mode == TEMPDRAW)
  1254.                     || (vp->mode == MARK) || (vp->mode == TEMPMARK) ||
  1255.                         (vp->mode == TEMPMOVE)))
  1256.             {
  1257.                 temppoint = (pointlist) NewPtr(sizeof(point));
  1258.                 vp->current->next = temppoint;
  1259.                 vp->current = temppoint;
  1260.                 vp->current->x = joinup(vp->nhix,vp->nlox,vp->nex);
  1261.                 vp->current->y = joinup(vp->nhiy,vp->nloy,vp->ney);
  1262.                 vp->current->next = (pointlist) NULL;
  1263.                 if ((vp->mode == TEMPDRAW) || (vp->mode == TEMPMOVE) ||
  1264.                     (vp->mode == TEMPMARK))
  1265.                     vp->mode = vp->modesave;
  1266.                 newcoord(vw);
  1267.             }
  1268.             else if (vp->mode == TEMPMOVE)
  1269.             {
  1270.                 vp->mode = vp->modesave;
  1271.                 newcoord(vw);
  1272.             }
  1273.             else if ((vp->mode == DRAW) || (vp->mode == TEMPDRAW))
  1274.             {
  1275.                 clipvec(vw,vp->curx,vp->cury,
  1276.                     joinup(vp->nhix,vp->nlox,vp->nex),
  1277.                     joinup(vp->nhiy,vp->nloy,vp->ney));
  1278.                 newcoord(vw);
  1279.                 if (vp->mode == TEMPDRAW) vp->mode = vp->modesave;
  1280.             }
  1281.             else if ((vp->mode == MARK) || (vp->mode == TEMPMARK))
  1282.             {
  1283.                 newcoord(vw);
  1284.                 if (vp->TEKtype) drawc(vw,127 + vp->TEKMarker);
  1285.                 newcoord(vw);
  1286.                 if (vp->mode == TEMPMARK) vp->mode = vp->modesave;
  1287.             }
  1288.         }
  1289.  
  1290.         if (state[vw] == CANCEL) state[vw] = DONE;
  1291.     } while (goagain);
  1292.     return;
  1293. }
  1294.  
  1295.  
  1296. /*  Clear screen and have a few other effects:
  1297.  *    - Return graphics to home position (0,3071)
  1298.  *    - Switch to alpha mode
  1299.  *    This is a standard Tek command; don't look at me.
  1300.  */
  1301. void VGpage
  1302.   (
  1303.     short vw
  1304.   )
  1305. {
  1306.     if (VGwin[vw]->TEKtype)
  1307.         (*RG[VGwin[vw]->RGdevice].pencolor)(VGwin[vw]->RGnum,VGwin[vw]->TEKBackground);
  1308.     else
  1309.         (*RG[VGwin[vw]->RGdevice].pencolor)(VGwin[vw]->RGnum,0);
  1310.     (*RG[VGwin[vw]->RGdevice].clrscr)(VGwin[vw]->RGnum);
  1311.     (*RG[VGwin[vw]->RGdevice].pencolor)(VGwin[vw]->RGnum,1);
  1312.     VGwin[vw]->mode = ALPHA;
  1313.     state[vw] = DONE;
  1314.     VGwin[vw]->textcol = 0;
  1315.     fontnum(vw,0);
  1316.     storexy(vw,0,3071);
  1317. }
  1318.  
  1319.  
  1320. /*
  1321.  *    Redraw window 'vw' in pieces to window 'dest'.
  1322.  *    Must call this function repeatedly to draw whole image.
  1323.  *    Only draws part of the image at a time, to yield CPU power.
  1324.  *    Returns 0 if needs to be called more, or 1 if the image
  1325.  *    is complete.  Another call would result in the redraw beginning again.
  1326.  *    User should clear screen before beginning redraw.
  1327.  */
  1328. short VGpred(short vw, short dest)
  1329. {
  1330. short        data;
  1331. TEKSTOREP    st = VGstore[vw];
  1332. short        count = 0;
  1333.     
  1334.     if (drawing[vw])        /* wasn't redrawing */
  1335.     {
  1336.         topTEKstore(VGstore[vw]);
  1337.         drawing[vw] = 0;    /* redraw incomplete */
  1338.     }
  1339.  
  1340.     while (++count < PREDCOUNT && ((data = nextTEKitem(st)) != -1))
  1341.         VGdraw(dest,data);
  1342.  
  1343.     if (data == -1) drawing[vw] = 1;     /* redraw complete */
  1344.     return(drawing[vw]);
  1345. }
  1346.  
  1347. void VGstopred
  1348.   (
  1349.     short vw
  1350.   )
  1351. /*
  1352.     Abort VGpred redrawing of specified window.
  1353.     Must call this routine if you decide not to complete the redraw.
  1354. */
  1355. {
  1356.     drawing[vw] = 1;
  1357. }
  1358.  
  1359.  
  1360. void VGredraw
  1361.   (
  1362.     short vw,
  1363.     short dest
  1364.   )
  1365. /*
  1366.  *    Redraw the contents of window 'vw' to window 'dest'.
  1367.  *    Does not yield CPU until done.
  1368.  *    User should clear the screen before calling this, to avoid 
  1369.  *    a messy display.
  1370.  */
  1371. {
  1372. short        data;
  1373.  
  1374.     topTEKstore(VGstore[vw]);
  1375.     while ((data = nextTEKitem(VGstore[vw])) != -1) VGdraw(dest,data);
  1376. }
  1377.  
  1378. void VGgiveinfo
  1379.   (
  1380.     short vw
  1381.   )
  1382. /*
  1383.  *    Send interesting information about the virtual window down to
  1384.  *    its RG, so that the RG can make VG calls and display zoom values
  1385.  */
  1386. {
  1387.     (*RG[VGwin[vw]->RGdevice].info)(VGwin[vw]->RGnum,
  1388.     vw,
  1389.     VGwin[vw]->winbot,
  1390.     VGwin[vw]->winleft,
  1391.     VGwin[vw]->wintop,
  1392.     VGwin[vw]->winright);
  1393. }
  1394.  
  1395. void VGzoom
  1396.   (
  1397.     short vw,
  1398.     short x0,
  1399.     short y0,
  1400.     short x1,
  1401.     short y1
  1402.   )
  1403. /*
  1404.  *    Set new borders for zoom/pan region.
  1405.  *    x0,y0 is lower left; x1,y1 is upper right.
  1406.  *    User should redraw after calling this.
  1407.  */
  1408. {
  1409.     VGwin[vw]->winbot = y0;
  1410.     VGwin[vw]->winleft = x0;
  1411.     VGwin[vw]->wintop = y1;
  1412.     VGwin[vw]->winright = x1;
  1413.     VGwin[vw]->wintall = y1 - y0 + 1;
  1414.     VGwin[vw]->winwide = x1 - x0 + 1;
  1415.     VGgiveinfo(vw);
  1416. }
  1417.  
  1418. void    VGwhatzoom(short vw, short *px0, short *py0, short *px1, short *py1)
  1419. {
  1420.     *py0 = VGwin[vw]->winbot;
  1421.     *px0 = VGwin[vw]->winleft;
  1422.     *py1 = VGwin[vw]->wintop;
  1423.     *px1 = VGwin[vw]->winright;
  1424. }
  1425.  
  1426. void VGzcpy
  1427.   (
  1428.     short src,
  1429.     short dest
  1430.   )
  1431. /*
  1432.  *    Set zoom/pan borders for window 'dest' equal to those for window 'src'.
  1433.  *    User should redraw window 'dest' after calling this.
  1434.  */
  1435. {
  1436.     VGzoom(dest,VGwin[src]->winleft, VGwin[src]->winbot,
  1437.     VGwin[src]->winright, VGwin[src]->wintop);
  1438. }
  1439.  
  1440. void VGclose
  1441.   (
  1442.     short vw
  1443.   )
  1444. /*
  1445.  *    Close virtual window.
  1446.  *    Release its real graphics device and its store.
  1447.  */
  1448. {
  1449.     (*RG[VGwin[vw]->RGdevice].close)(VGwin[vw]->RGnum);
  1450.     freeTEKstore(VGstore[vw]);
  1451.     VGwin[vw]->RGdevice = -1;
  1452. }
  1453.  
  1454. short VGwrite
  1455.   (
  1456.     short vw,
  1457.     char *data,
  1458.     short count
  1459.   )
  1460. /*
  1461.  *    Draw the data pointed to by 'data' of length 'count'
  1462.  *    on window vw, and add it to the store for that window.
  1463.  *    This is THE way for user program to pass Tektronix data.
  1464.  */
  1465. {
  1466. char *c = data;
  1467. char *end = &(data[count]);
  1468. char storeit = storing[vw];
  1469.  
  1470.     if ((VGwin[vw]->RGdevice == -1) || (vw >= MAXVG) || (vw < 0)) return(-1);
  1471.         /* window not open */
  1472.  
  1473.     while (c != end)
  1474.     {
  1475.         if (*c == 24)                /* ASC CAN character */
  1476.             return(c-data+1);
  1477.         if (storeit) addTEKstore(VGstore[vw],*c);
  1478.         VGdraw(vw,*c++);
  1479.  
  1480.     }
  1481.     return(count);
  1482. }
  1483.  
  1484. char *
  1485. VGrgname(short rgdev)
  1486. /*
  1487.  *    Return a pointer to a human-readable string
  1488.  *    which describes the specified real device
  1489.  */
  1490. {
  1491.     return(*RG[rgdev].devname)();
  1492. }
  1493.  
  1494. void    VGtmode(short rgdev)
  1495. /* Put the specified real device into text mode */
  1496. {
  1497.     (*RG[rgdev].tmode)();
  1498. }
  1499.  
  1500.  
  1501. void VGgindata
  1502.   (
  1503.     short vw,
  1504.     unsigned short x,        /* NCSA: SB - gimme credit for UNSIGNED data */
  1505.     unsigned short y,        /* NCSA: SB - me too */
  1506.     char c,
  1507.     char *a
  1508.   )
  1509. /*
  1510.  *    Translate data for output as GIN report.
  1511.  *
  1512.  *    User indicates VW number and x,y coordinates of the GIN cursor.
  1513.  *    Coordinate space is 0-4095, 0-4095 with 0,0 at the bottom left of
  1514.  *    the real window and 4095,4095 at the upper right of the real window.
  1515.  *    'c' is the character to be returned as the keypress.
  1516.  *    'a' is a pointer to an array of 5 characters.  The 5 chars must
  1517.  *    be transmitted by the user to the remote host as the GIN report.
  1518.  */
  1519. {
  1520.     long x2,y2;
  1521.  
  1522.     x2 = ((x * VGwin[vw]->winwide) / INXMAX + VGwin[vw]->winleft) >> 2;
  1523.     y2 = ((y * VGwin[vw]->wintall) / INYMAX + VGwin[vw]->winbot) >> 2;
  1524.  
  1525.     a[0] = c;
  1526.     a[1] = 0x20 | ((x2 & 0x03E0) >> 5);
  1527.     a[2] = 0x20 | (x2 & 0x001F);
  1528.     a[3] = 0x20 | ((y2 & 0x03E0) >> 5);
  1529.     a[4] = 0x20 | (y2 & 0x001F);
  1530. }
  1531.  
  1532.  
  1533.  
  1534.  
  1535.  
  1536. short VGgetVS(short theVGnum)                /* NCSA 2.5: give us the VS */
  1537. {                                            /* NCSA 2.5 */
  1538.     return VGwin[theVGnum]->theVS;            /* NCSA 2.5 */
  1539. }                                            /* NCSA 2.5 */
  1540.